home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 37 / IOPROG_37.ISO / SOFT / Multilizer.exe / disk1 / data1.cab / data1 / [Group9]VCL Source Standard / ivmlutil.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-12  |  41.5 KB  |  1,684 lines

  1. unit IvMlUtil;
  2.  
  3. {$I IVMULTI.INC}
  4.  
  5. interface
  6.  
  7. uses
  8. {$IFDEF WIN32}
  9.   Windows,
  10. {$ELSE}
  11.   WinTypes, WinProcs,
  12. {$ENDIF}
  13.   SysUtils, Classes, Graphics, Forms, Dialogs, Controls, FileCtrl,
  14.   IvDictio;
  15.  
  16. const
  17.   { Measurement conversion constants }
  18.  
  19.   INCH_IN_FEET_C = 12;
  20.   FEET_IN_YARD_C = 3;
  21.   YARDS_IN_FURLONG_C = 220;
  22.   FURLONGS_IN_MILE_C = 8;
  23.  
  24.   INCH_IN_METERS_C: Single = 0.0254;
  25.   FOOT_IN_METERS_C: Single = 0.3048;
  26.   YARD_IN_METERS_C: Single = 0.9144;
  27.   FURLONG_IN_METERS_C: Single = 201.2;
  28.   MILE_IN_METERS: Single = 1609.3;
  29.  
  30.   OUNCES_IN_POUND_C = 16;
  31.   POUNDS_IN_TON_C = 2000;
  32.  
  33.   OUNCE_IN_KILOGRAMS_C: Single = 0.02835;
  34.   POUND_IN_KILOGRAMS_C: Single = 0.453;
  35.   TON_IN_KILOGRAMS_C: Single = 907;
  36.  
  37.   CAPTIONS_C: array[TMsgDlgType] of String =
  38.   (
  39.     'Warning',
  40.     'Error',
  41.     'Information',
  42.     'Confirm',
  43.     ''
  44.   );
  45.   BUTTONCAPTIONS_C: array[TMsgDlgBtn] of String =
  46.   (
  47.     '&Yes',
  48.     '&No',
  49.     'OK',
  50.     'Cancel',
  51.     '&Abort',
  52.     '&Retry',
  53.     '&Ignore',
  54.     '&All',
  55. {$IFDEF IVWIDE}
  56.     'N&o to All',
  57.     'Y&es to All',
  58. {$ENDIF}
  59.     '&Help'
  60.   );
  61.  
  62. type
  63.   { Measurement types }
  64.  
  65.   TIvMetricLength = (ivmlmm, ivmlcm, ivmldm, ivmlm, ivmlkm);
  66.   TIvUSLength = (ivulInch, ivulFoot, ivulYard, ivulFurlong, ivulMile);
  67.  
  68.   TIvMetricArea = (ivmacm2, ivmam2, ivmaAre, ivmaHectare, ivmakm2);
  69.   TIvUSArea = (ivuaInch2, ivuaFoot2, ivuaYard2, ivuaAcre, ivuaMile2);
  70.  
  71.   TIvMetricCapacity = (ivmcml, ivmccl, ivmcdl, ivmcl, ivmcm3);
  72.   TIvUSLiquidCapacity = (ivulOunce, ivulPint, ivulGallon);
  73.   TIvUSDryCapacity = (ivudPint, ivudBushel);
  74.  
  75.   TIvMetricWeight = (ivmwg, ivmwkg, ivmwt);
  76.   TIvUSWeight = (ivuwOunce, ivuwPound, ivuwTon);
  77.  
  78.   TIvMetricTemperature = (ivmtC, ivmtK);
  79.   TIvUSTemperature = (ivutF);
  80.  
  81.   TIvUSQuantity = (ivusqNone, ivusqShort, ivusqLong, ivusqSymbol);
  82.  
  83. function IvWeek(
  84.   date: TDateTime;
  85.   firstWeekOfYear: TIvFirstWeekOfYear;
  86.   firstDayOfWeek: TIvDayOfWeek): Integer;
  87.  
  88. function IvWeekEx(date: TDateTime): Integer;
  89.  
  90. function IvDayOfWeek(date: TDateTime): TIvDayOfWeek;
  91.  
  92. function IvDayOfWeekNumber(
  93.   date: TDateTime;
  94.   firstDayOfWeek: TIvDayOfWeek): Integer;
  95.  
  96. function IvFirstDayOfWeek(
  97.   date: TDateTime;
  98.   firstDayOfWeek: TIvDayOfWeek): TDateTime;
  99.  
  100. function IvFirstDayOfMonth(date: TDateTime): TDateTime;
  101.  
  102. function IvFirstDayOfYear(date: TDateTime): TDateTime;
  103.  
  104. function IvFirstWeekOfMonth(
  105.   date: TDateTime;
  106.   firstWeekOfYear: TIvFirstWeekOfYear;
  107.   firstDayOfWeek: TIvDayOfWeek): Integer;
  108.  
  109. function IvVCLDayToDay(index: Integer): Integer;
  110.  
  111. { Measurement functions }
  112.  
  113. function IvFormatGeneric(
  114.   measurementSystem: TIvMeasurementSystem;
  115.   value, normalizedValue: Double;
  116.   metricUnit: Integer;
  117.   const metricFormat: String;
  118.   usUnit: Integer;
  119.   const usFormat: String;
  120.   metricTable: array of String;
  121.   symbolUsTable: array of String;
  122.   shortUsTable: array of String;
  123.   singleUsTable: array of String;
  124.   pruralUsTable: array of String;
  125.   usRatiosTable: array of Integer;
  126.   usToMetricTable: array of Single): String;
  127.  
  128. function IvFormatLength(
  129.   measurementSystem: TIvMeasurementSystem;
  130.   value: Double;
  131.   metricUnit: TIvMetricLength;
  132.   const metricFormat: String;
  133.   usUnit: TIvUSLength;
  134.   const usFormat: String): String;
  135.  
  136. function IvFormatArea(
  137.   measurementSystem: TIvMeasurementSystem;
  138.   value: Double;
  139.   metricUnit: TIvMetricArea;
  140.   const metricFormat: String;
  141.   usUnit: TIvUSArea;
  142.   const usFormat: String): String;
  143.  
  144. function IvFormatLiquidCapacity(
  145.   measurementSystem: TIvMeasurementSystem;
  146.   value: Double;
  147.   metricUnit: TIvMetricCapacity;
  148.   const metricFormat: String;
  149.   usUnit: TIvUSLiquidCapacity;
  150.   const usFormat: String): String;
  151.  
  152. function IvFormatDryCapacity(
  153.   measurementSystem: TIvMeasurementSystem;
  154.   value: Double;
  155.   metricUnit: TIvMetricCapacity;
  156.   const metricFormat: String;
  157.   usUnit: TIvUSDryCapacity;
  158.   const usFormat: String): String;
  159.  
  160. function IvFormatWeight(
  161.   measurementSystem: TIvMeasurementSystem;
  162.   value: Double;
  163.   metricUnit: TIvMetricWeight;
  164.   const metricFormat: String;
  165.   usUnit: TIvUSWeight;
  166.   const usFormat: String): String;
  167.  
  168. function IvFormatTemperature(
  169.   measurementSystem: TIvMeasurementSystem;
  170.   value: Double;
  171.   metricUnit: TIvMetricTemperature;
  172.   const metricFormat: String;
  173.   usUnit: TIvUSTemperature;
  174.   const usFormat: String): String;
  175.  
  176. { Message and input dialogs }
  177.  
  178. function IvMessageBox(
  179.   const msg, captionMsg: String;
  180.   dlgType: TMsgDlgType;
  181.   buttons: TMsgDlgButtons;
  182.   helpContext: Longint;
  183.   dictionary: TIvDictionary): Integer;
  184.  
  185. function IvMessageBoxPos(
  186.   const msg, captionMsg: String;
  187.   dlgType: TMsgDlgType;
  188.   buttons: TMsgDlgButtons;
  189.   helpContext: Longint;
  190.   x, y: Integer;
  191.   dictionary: TIvDictionary): Integer;
  192.  
  193. procedure IvShowMessage(const msg: String; dictionary: TIvDictionary);
  194. procedure IvShowMessagePos(const msg: String; X, Y: Integer; dictionary: TIvDictionary);
  195.  
  196. { Extended message dialogs }
  197.  
  198. function IvMessageBoxEx(
  199.   const msg, captionMsg: String;
  200.   dlgType: TMsgDlgType;
  201.   buttons: TMsgDlgButtons;
  202.   helpContext: Longint;
  203.   dictionary: TIvDictionary): Integer;
  204.  
  205. function IvMessageBoxPosEx(
  206.   const msg, captionMsg: String;
  207.   dlgType: TMsgDlgType;
  208.   buttons: TMsgDlgButtons;
  209.   helpContext: Longint;
  210.   x, y: Integer;
  211.   dictionary: TIvDictionary): Integer;
  212.  
  213. { Input dialogs }
  214.  
  215. function IvInputBox(const captionMsg, prompt, def: String; dictionary: TIvDictionary): String;
  216. function IvInputQuery(const captionMsg, prompt: String; var value: String; dictionary: TIvDictionary): Boolean;
  217.  
  218. { Directory functions }
  219.  
  220. function IvSelectDirectory(
  221.   var directory: String;
  222.   options: TSelectDirOpts;
  223.   helpContext: Longint;
  224.   dictionary: TIvDictionary): Boolean;
  225.  
  226. { IV StayOnTop: If this var is TRUE then TIvMLForm objects will be fsStayOnTop }
  227. var
  228.   IvFormAlwaysStayOnTop: boolean;
  229.  
  230.  
  231. implementation
  232.  
  233. uses
  234.   StdCtrls, ExtCtrls,
  235.   IvMulti, IvMlCons;
  236.  
  237.  
  238. function MaxInteger(a, b: Integer): Integer;
  239. begin
  240.   if a >= b then
  241.     Result := a
  242.   else
  243.     Result := b;
  244. end;
  245.  
  246. function IvWeek(
  247.   date: TDateTime;
  248.   firstWeekOfYear: TIvFirstWeekOfYear;
  249.   firstDayOfWeek: TIvDayOfWeek): Integer;
  250. var
  251.   number: Integer;
  252.   first: TDateTime;
  253. begin
  254.   { Gets the number of the first day of the week.
  255.     Depending on FirstWeekOfYear variable counts the date of the first day
  256.     of the first week. }
  257.  
  258.   first := IvFirstDayOfYear(date);
  259.   number := IvDayOfWeekNumber(first, firstDayOfWeek);
  260.   case firstWeekOfYear of
  261.     ivfwFirstPart:
  262.       first := first - number + 1;
  263.  
  264.     ivfwFirstFull:
  265.       if number > 0 then
  266.         first := first + 7 - number + 1;
  267.  
  268.     ivfwFirst4:
  269.       if number <= 3 then
  270.         first := first - number + 1
  271.       else
  272.         first := first + 7 - number;
  273.   end;
  274.  
  275.   { Finally calculates the difference between the current day and the first
  276.     day of the first week. Divedes the difference by 7 to get the amount of
  277.     week and adds 1 so that the first week is 1 }
  278.  
  279.   Result := Trunc(date - first) div 7 + 1;
  280. end;
  281.  
  282. function IvWeekEx(date: TDateTime): Integer;
  283. begin
  284.   Result := IvWeek(date, ivfwFirstPart, ivwdMonday);
  285. end;
  286.  
  287. function IvDayOfWeek(date: TDateTime): TIvDayOfWeek;
  288. begin
  289.   { DayOfWeek returns 1 as the first day but it is Sunday
  290.     1 + 5 mod 7 = 6 (ivwdSunday)
  291.     2 + 5 mod 7 = 0 (ivwdMonday) }
  292.  
  293.   Result := TIvDayOfWeek((DayOfWeek(date) + 5) mod 7);
  294. end;
  295.  
  296. function IvDayOfWeekNumber(
  297.   date: TDateTime;
  298.   firstDayOfWeek: TIvDayOfWeek): Integer;
  299. begin
  300.   { Calculates the difference between the current day and the first day of
  301.     week. Add one to the result because the first day of week is 1 }
  302.  
  303.   Result := Integer(IvDayOfWeek(date)) - Integer(firstDayOfWeek);
  304.   if Result < 0 then
  305.     Result := 6 + Result;
  306.   Result := Result + 1;
  307. end;
  308.  
  309. function IvFirstDayOfWeek(
  310.   date: TDateTime;
  311.   firstDayOfWeek: TIvDayOfWeek): TDateTime;
  312. begin
  313.   Result := date - IvDayOfWeekNumber(date, firstDayOfWeek) + 1;
  314. end;
  315.  
  316. function IvFirstDayOfMonth(date: TDateTime): TDateTime;
  317. var
  318.   year, month, day: Word;
  319. begin
  320.   DecodeDate(date, year, month, day);
  321.   Result := EncodeDate(year, month, 1);
  322. end;
  323.  
  324. function IvFirstDayOfYear(date: TDateTime): TDateTime;
  325. var
  326.   year, month, day: Word;
  327. begin
  328.   DecodeDate(date, year, month, day);
  329.   Result := EncodeDate(year, 1, 1);
  330. end;
  331.  
  332. function IvFirstWeekOfMonth(
  333.   date: TDateTime;
  334.   firstWeekOfYear: TIvFirstWeekOfYear;
  335.   firstDayOfWeek: TIvDayOfWeek): Integer;
  336. begin
  337.   Result := IvWeek(IvFirstDayOfMonth(date), firstWeekOfYear, firstDayOfWeek);
  338. end;
  339.  
  340. function IvVCLDayToDay(index: Integer): Integer;
  341. begin
  342.   Result := (index + 5) mod 7;
  343. end;
  344.  
  345.  
  346. { Measurement functions }
  347.  
  348. procedure ParseUSFormat(
  349.   const format: String;
  350.   var quantity: TIvUSQuantity;
  351.   var digits, subDigits: Integer);
  352. begin
  353.   if Length(format) >= 1 then
  354.     quantity := TIvUSQuantity(StrToInt(format[1]))
  355.   else
  356.     quantity := ivusqShort;
  357.  
  358.   if Length(format) >= 2 then
  359.     digits := StrToInt(format[2])
  360.   else
  361.     digits := 0;
  362.  
  363.   if Length(format) >= 3 then
  364.     subDigits := StrToInt(format[3])
  365.   else
  366.     subDigits := 0;
  367. end;
  368.  
  369. function IvFormatGeneric(
  370.   measurementSystem: TIvMeasurementSystem;
  371.   value, normalizedValue: Double;
  372.   metricUnit: Integer;
  373.   const metricFormat: String;
  374.   usUnit: Integer;
  375.   const usFormat: String;
  376.   metricTable: array of String;
  377.   symbolUsTable: array of String;
  378.   shortUsTable: array of String;
  379.   singleUsTable: array of String;
  380.   pruralUsTable: array of String;
  381.   usRatiosTable: array of Integer;
  382.   usToMetricTable: array of Single): String;
  383. var
  384.   i, real, fraction, nominator, newNominator, subRatio, digits, sub: Integer;
  385.   quantity: TIvUSQuantity;
  386. begin
  387.   if MeasurementSystem = ivmsMetric then
  388.     { Format metric }
  389.  
  390.     Result := Format(metricFormat, [value, metricTable[metricUnit]])
  391.   else
  392.   begin
  393.     { Format us }
  394.  
  395.     ParseUSFormat(usFormat, quantity, digits, sub);
  396.     subRatio := 1;
  397.     for i := 1 to sub do
  398.       subRatio := subRatio*usRatiosTable[usUnit - i];
  399.  
  400.     value := normalizedValue/usToMetricTable[usUnit];
  401.     if (digits = 0) and (sub = 0) then
  402.     begin
  403.       real := Round(value);
  404.       fraction := 0;
  405.       nominator := 1;
  406.     end
  407.     else if sub > 0 then
  408.     begin
  409.       real := Trunc(value);
  410.       fraction := Round(subRatio*(value - real));
  411.       if fraction = subRatio then
  412.       begin
  413.         Inc(real);
  414.         fraction := 0;
  415.       end;
  416.       nominator := 1;
  417.     end
  418.     else
  419.     begin
  420.       nominator := 2;
  421.       for i := 1 to digits - 1 do
  422.         nominator := 2*nominator;
  423.       real := Trunc(value);
  424.       fraction := Round(nominator*(value - real));
  425.       if fraction = nominator then
  426.       begin
  427.         Inc(real);
  428.         fraction := 0;
  429.       end;
  430.  
  431.       if fraction <> 0 then
  432.       begin
  433.         i := nominator;
  434.         newNominator := 2;
  435.         while i > 1 do
  436.         begin
  437.           i := i div 2;
  438.           if (fraction mod i) = 0 then
  439.           begin
  440.             nominator := newNominator;
  441.             fraction := fraction div i;
  442.             Break;
  443.           end;
  444.           newNominator := 2*newNominator;
  445.         end;
  446.       end;
  447.     end;
  448.  
  449.     if sub = 0 then
  450.     begin
  451.       Result := IntToStr(real);
  452.       if fraction > 0 then
  453.         Result := Result + ' ' + IntToStr(fraction) + '/' + IntToStr(nominator);
  454.  
  455.       case quantity of
  456.         ivusqShort: Result := Result + ' ' + shortUsTable[usUnit];
  457.         ivusqLong: if Result = '1' then
  458.              Result := Result + ' ' + singleUsTable[usUnit]
  459.            else
  460.              Result := Result + ' ' + pruralUsTable[usUnit];
  461.       end;
  462.     end
  463.     else
  464.     begin
  465.       real := Trunc(value);
  466.       fraction := Round(subRatio*(value - real));
  467.       if fraction = subRatio then
  468.       begin
  469.         Inc(real);
  470.         fraction := 0;
  471.       end;
  472.       Result := IntToStr(real);
  473.  
  474.       case quantity of
  475.         ivusqNone: if fraction > 0 then
  476.              Result := Result + ' ' + IntToStr(fraction);
  477.  
  478.         ivusqSymbol: begin
  479.              Result := Result + symbolUsTable[usUnit];
  480.              if fraction > 0 then
  481.                Result := Result + IntToStr(fraction) + symbolUsTable[usUnit - sub];
  482.            end;
  483.  
  484.         ivusqShort: begin
  485.              Result := Result + ' ' + shortUsTable[usUnit];
  486.              if fraction > 0 then
  487.                Result := Result + ' ' + IntToStr(fraction) + ' ' + shortUsTable[usUnit - sub];
  488.            end;
  489.  
  490.         ivusqLong: if (Result = '1') and (fraction = 0) then
  491.              Result := Result + ' ' + singleUsTable[usUnit]
  492.            else
  493.            begin
  494.              Result := Result + ' ' + pruralUsTable[usUnit];
  495.              if fraction > 0 then
  496.                Result := Result + ' ' + IntToStr(fraction) + ' ' + pruralUsTable[usUnit - sub];
  497.            end;
  498.       end;
  499.     end;
  500.   end;
  501. end;
  502.  
  503. function IvFormatLength(
  504.   measurementSystem: TIvMeasurementSystem;
  505.   value: Double;
  506.   metricUnit: TIvMetricLength;
  507.   const metricFormat: String;
  508.   usUnit: TIvUSLength;
  509.   const usFormat: String): String;
  510. var
  511.   normalizedValue: Double;
  512. begin
  513.   case metricUnit of
  514.     ivmlmm: normalizedValue := value/1000;
  515.     ivmlcm: normalizedValue := value/100;
  516.     ivmldm: normalizedValue := value/10;
  517.     ivmlkm: normalizedValue := 1000*value;
  518.   else
  519.     normalizedValue := value;
  520.   end;
  521.  
  522.   Result := IvFormatGeneric(
  523.     measurementSystem,
  524.     value,
  525.     normalizedValue,
  526.     Integer(metricUnit),
  527.     metricFormat,
  528.     Integer(usUnit),
  529.     usFormat,
  530.     ['mm', 'cm', 'dm', 'm', 'km'],
  531.     ['''''', '''', 'yd', 'fl', 'mi'],
  532.     ['in', 'ft', 'yd', 'fl', 'mi'],
  533.     ['inch', 'foot', 'yard', 'furlong', 'mile'],
  534.     ['inches', 'feet', 'yards', 'furlongs', 'miles'],
  535.     [INCH_IN_FEET_C, FEET_IN_YARD_C, YARDS_IN_FURLONG_C, FURLONGS_IN_MILE_C, 0],
  536.     [INCH_IN_METERS_C, FOOT_IN_METERS_C, YARD_IN_METERS_C, FURLONG_IN_METERS_C, MILE_IN_METERS]);
  537. end;
  538.  
  539. function IvFormatArea(
  540.   measurementSystem: TIvMeasurementSystem;
  541.   value: Double;
  542.   metricUnit: TIvMetricArea;
  543.   const metricFormat: String;
  544.   usUnit: TIvUSArea;
  545.   const usFormat: String): String;
  546. var
  547.   normalizedValue: Double;
  548. begin
  549.   case metricUnit of
  550.     ivmacm2: normalizedValue := value/10000;
  551.     ivmaAre: normalizedValue := 100*value;
  552.     ivmaHectare: normalizedValue := 10000*value;
  553.     ivmakm2: normalizedValue := 1000000*value;
  554.   else
  555.     normalizedValue := value;
  556.   end;
  557.  
  558.   Result := IvFormatGeneric(
  559.     measurementSystem,
  560.     value,
  561.     normalizedValue,
  562.     Integer(metricUnit),
  563.     metricFormat,
  564.     Integer(usUnit),
  565.     usFormat,
  566.     ['cm2', 'm2', 'a', 'ha', 'km2'],
  567.     ['sq in2', 'sq ft', 'sq yd', 'acre', 'sq mi'],
  568.     ['sq in2', 'sq ft', 'sq yd', 'acre', 'sq mi'],
  569.     ['square inch', 'square foot', 'square yard', 'acre', 'square mile'],
  570.     ['square inches', 'square feet', 'square yards', 'acres', 'square miles'],
  571.     [144, 9, 4840, 640, 0],
  572.     [0.00064583, 0.093, 0.8361, 4047, 2590000]);
  573. end;
  574.  
  575. function IvFormatLiquidCapacity(
  576.   measurementSystem: TIvMeasurementSystem;
  577.   value: Double;
  578.   metricUnit: TIvMetricCapacity;
  579.   const metricFormat: String;
  580.   usUnit: TIvUSLiquidCapacity;
  581.   const usFormat: String): String;
  582. var
  583.   normalizedValue: Double;
  584. begin
  585.   case metricUnit of
  586.     ivmcml: normalizedValue := value/1000;
  587.     ivmccl: normalizedValue := value/100;
  588.     ivmcdl: normalizedValue := value/10;
  589.     ivmcm3: normalizedValue := 1000*value;
  590.   else
  591.     normalizedValue := value;
  592.   end;
  593.  
  594.   Result := IvFormatGeneric(
  595.     measurementSystem,
  596.     value,
  597.     normalizedValue,
  598.     Integer(metricUnit),
  599.     metricFormat,
  600.     Integer(usUnit),
  601.     usFormat,
  602.     ['ml', 'cl', 'dl', 'l', 'm3'],
  603.     ['fl oz', 'pt', 'gal'],
  604.     ['fl oz', 'pt', 'gal'],
  605.     ['fluid ounce', 'pint', 'gallon'],
  606.     ['fluid ounces', 'pints', 'gallons'],
  607.     [16, 8, 0],
  608.     [0.0296, 0.4732, 3.7853]);
  609. end;
  610.  
  611. function IvFormatDryCapacity(
  612.   measurementSystem: TIvMeasurementSystem;
  613.   value: Double;
  614.   metricUnit: TIvMetricCapacity;
  615.   const metricFormat: String;
  616.   usUnit: TIvUSDryCapacity;
  617.   const usFormat: String): String;
  618. var
  619.   normalizedValue: Double;
  620. begin
  621.   case metricUnit of
  622.     ivmcml: normalizedValue := value/1000;
  623.     ivmccl: normalizedValue := value/100;
  624.     ivmcdl: normalizedValue := value/10;
  625.     ivmcm3: normalizedValue := 1000*value;
  626.   else
  627.     normalizedValue := value;
  628.   end;
  629.  
  630.   Result := IvFormatGeneric(
  631.     measurementSystem,
  632.     value,
  633.     normalizedValue,
  634.     Integer(metricUnit),
  635.     metricFormat,
  636.     Integer(usUnit),
  637.     usFormat,
  638.     ['ml', 'cl', 'dl', 'l', 'm3'],
  639.     ['pt', 'bu'],
  640.     ['pt', 'bu'],
  641.     ['pint', 'bushel'],
  642.     ['pints', 'bushels'],
  643.     [64, 0],
  644.     [0.5506, 35.239]);
  645. end;
  646.  
  647. function IvFormatWeight(
  648.   measurementSystem: TIvMeasurementSystem;
  649.   value: Double;
  650.   metricUnit: TIvMetricWeight;
  651.   const metricFormat: String;
  652.   usUnit: TIvUSWeight;
  653.   const usFormat: String): String;
  654. var
  655.   normalizedValue: Double;
  656. begin
  657.   case metricUnit of
  658.     ivmwg: normalizedValue := value/1000;
  659.     ivmwt: normalizedValue := 1000*value;
  660.   else
  661.     normalizedValue := value;
  662.   end;
  663.  
  664.   Result := IvFormatGeneric(
  665.     measurementSystem,
  666.     value,
  667.     normalizedValue,
  668.     Integer(metricUnit),
  669.     metricFormat,
  670.     Integer(usUnit),
  671.     usFormat,
  672.     ['g', 'kg', 't'],
  673.     ['oz', 'lb', 'ton'],
  674.     ['oz', 'lb', 'ton'],
  675.     ['ounce', 'pound', 'ton'],
  676.     ['ounces', 'pounds', 'tons'],
  677.     [OUNCES_IN_POUND_C, POUNDS_IN_TON_C, 0],
  678.     [OUNCE_IN_KILOGRAMS_C, POUND_IN_KILOGRAMS_C, TON_IN_KILOGRAMS_C]);
  679. end;
  680.  
  681. function IvFormatTemperature(
  682.   measurementSystem: TIvMeasurementSystem;
  683.   value: Double;
  684.   metricUnit: TIvMetricTemperature;
  685.   const metricFormat: String;
  686.   usUnit: TIvUSTemperature;
  687.   const usFormat: String): String;
  688. const
  689.   METRIC_C: array[TIvMetricTemperature] of String = ('░C', 'K');
  690.   US_C: array[TIvUSTemperature] of String = ('░F');
  691. begin
  692.   if MeasurementSystem = ivmsMetric then
  693.     Result := Format(metricFormat, [value, METRIC_C[metricUnit]])
  694.   else
  695.   begin
  696.     if metricUnit = ivmtK then
  697.       value := value - 273.15;
  698.     value := 1.8*value + 32;
  699.     Result := Format(usFormat, [value, US_C[usUnit]])
  700.   end;
  701. end;
  702.  
  703.  
  704. { Message and input dialogs }
  705.  
  706. type
  707.   TIvMLForm = class(TForm)
  708.   protected
  709.     FTranslator: TIvTranslator;
  710.  
  711.     constructor CreateML(owner: TComponent; dictionary: TIvDictionary);
  712.   end;
  713.  
  714.   TIvMessageForm = class(TIvMLForm)
  715.   private
  716.     FMsg: TLabel;
  717.  
  718.     procedure Restrict(
  719.       translator: TIvTranslator;
  720.       obj: TObject;
  721.       const name: String;
  722.       var translate: Boolean);
  723.  
  724.     procedure HelpButtonClick(Sender: TObject);
  725.  
  726.   protected
  727.     constructor CreateML(
  728.       owner: TComponent;
  729.       const msg, captionMsg: String;
  730.       dlgType: TMsgDlgType;
  731.       buttons: TMsgDlgButtons;
  732.       dictionary: TIvDictionary;
  733.       translateMsg: Boolean);
  734.   end;
  735.  
  736. function GetAveCharSize(Canvas: TCanvas): TPoint;
  737. var
  738.   i: Integer;
  739.   buffer: array[0..51] of Char;
  740. begin
  741.   for i := 0 to 25 do
  742.     buffer[i] := Chr(i + Ord('A'));
  743.   for i := 0 to 25 do
  744.     buffer[i + 26] := Chr(i + Ord('a'));
  745.   GetTextExtentPoint(Canvas.Handle, buffer, 52, TSize(Result));
  746.   Result.X := Result.X div 52;
  747. end;
  748.  
  749. constructor TIvMlForm.CreateML(owner: TComponent; dictionary: TIvDictionary);
  750. begin
  751. {$IFDEF VER93}
  752.   inherited CreateNew(owner, 0);
  753. {$ELSE}
  754.   inherited CreateNew(owner);
  755. {$ENDIF}
  756.  
  757.   { IV StayOnTop: Always stay on top type of form? }
  758.   if IvFormAlwaysStayOnTop then
  759.     Self.FormStyle := fsStayOnTop;
  760.  
  761.   FTranslator := TIvTranslator.Create(Self);
  762.   FTranslator.Dictionary := dictionary;
  763.   FTranslator.Targets.Add(TIvTargetProperty.Create('', 'Caption', ivttInclude));
  764. end;
  765.  
  766. constructor TIvMessageForm.CreateML(
  767.   owner: TComponent;
  768.   const msg, captionMsg: String;
  769.   dlgType: TMsgDlgType;
  770.   buttons: TMsgDlgButtons;
  771.   dictionary: TIvDictionary;
  772.   translateMsg: Boolean);
  773. const
  774.   mcHorzMargin = 8;
  775.   mcVertMargin = 8;
  776.   mcHorzSpacing = 10;
  777.   mcVertSpacing = 10;
  778.   mcButtonWidth = 50;
  779.   mcButtonHeight = 14;
  780.   mcButtonSpacing = 4;
  781.   ICONIDS_C: array[TMsgDlgType] of PChar = (IDI_EXCLAMATION, IDI_HAND,
  782.     IDI_ASTERISK, IDI_QUESTION, nil);
  783.   BUTTONNAMES_C: array[TMsgDlgBtn] of string = (
  784.     'Yes', 'No', 'OK', 'Cancel', 'Abort', 'Retry', 'Ignore', 'All',
  785. {$IFDEF IVWIDE}
  786.     'NoToAll', 'YesToAll',
  787. {$ENDIF}
  788.     'Help');
  789.   MODALRESULTS_C: array[TMsgDlgBtn] of Integer = (
  790.     mrYes, mrNo, mrOk, mrCancel, mrAbort, mrRetry, mrIgnore, mrAll,
  791. {$IFDEF IVWIDE}
  792.     mrNoToAll, mrYesToAll,
  793. {$ENDIF}
  794.     0);
  795. var
  796.   DialogUnits: TPoint;
  797.   HorzMargin, VertMargin, HorzSpacing, VertSpacing, ButtonWidth,
  798.   ButtonHeight, ButtonSpacing, ButtonCount, ButtonGroupWidth,
  799.   IconTextWidth, IconTextHeight, X: Integer;
  800.   B, DefaultButton, CancelButton: TMsgDlgBtn;
  801.   IconID: PChar;
  802.   TextRect: TRect;
  803.   str: String;
  804. {$IFNDEF WIN32}
  805.   buffer: array[0..255] of Char;
  806. {$ENDIF}
  807. begin
  808.   inherited CreateML(owner, dictionary);
  809.  
  810.   BorderStyle := bsDialog;
  811.   Canvas.Font := Font;
  812.   DialogUnits := GetAveCharSize(Canvas);
  813.   HorzMargin := MulDiv(mcHorzMargin, DialogUnits.X, 4);
  814.   VertMargin := MulDiv(mcVertMargin, DialogUnits.Y, 8);
  815.   HorzSpacing := MulDiv(mcHorzSpacing, DialogUnits.X, 4);
  816.   VertSpacing := MulDiv(mcVertSpacing, DialogUnits.Y, 8);
  817.   ButtonWidth := MulDiv(mcButtonWidth, DialogUnits.X, 4);
  818.   ButtonHeight := MulDiv(mcButtonHeight, DialogUnits.Y, 8);
  819.   ButtonSpacing := MulDiv(mcButtonSpacing, DialogUnits.X, 4);
  820.   SetRect(TextRect, 0, 0, Screen.Width div 2, 0);
  821.   if dictionary <> nil then
  822.     str := dictionary.Translate(msg)
  823.   else
  824.     str := msg;
  825.   DrawText(
  826.     Canvas.Handle,
  827. {$IFDEF WIN32}PChar({$ELSE}StrPCopy(buffer,{$ENDIF}
  828.     str),
  829.     -1,
  830.     TextRect,
  831.     DT_EXPANDTABS or DT_CALCRECT or DT_WORDBREAK);
  832.   IconID := ICONIDS_C[DlgType];
  833.   IconTextWidth := TextRect.Right;
  834.   IconTextHeight := TextRect.Bottom;
  835.   if IconID <> nil then
  836.   begin
  837.     Inc(IconTextWidth, 32 + HorzSpacing);
  838.     if IconTextHeight < 32 then
  839.       IconTextHeight := 32;
  840.   end;
  841.   ButtonCount := 0;
  842.   for B := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
  843.     if B in Buttons then Inc(ButtonCount);
  844.   ButtonGroupWidth := 0;
  845.   if ButtonCount <> 0 then
  846.     ButtonGroupWidth :=
  847.       ButtonWidth * ButtonCount + ButtonSpacing * (ButtonCount - 1);
  848.   ClientWidth := MaxInteger(IconTextWidth, ButtonGroupWidth) + HorzMargin * 2;
  849.   ClientHeight :=
  850.     IconTextHeight + ButtonHeight + VertSpacing + VertMargin * 2;
  851.   Left := (Screen.Width div 2) - (Width div 2);
  852.   Top := (Screen.Height div 2) - (Height div 2);
  853.   if captionMsg = '' then
  854.   begin
  855.     if DlgType = mtCustom then
  856.       Caption := Application.Title
  857.     else
  858.       Caption := CAPTIONS_C[DlgType];
  859.   end
  860.   else
  861.     Caption := captionMsg;
  862.   if IconID <> nil then
  863.     with TImage.Create(Self) do
  864.     begin
  865.       Name := 'Image';
  866.       Parent := Self;
  867.       Picture.Icon.Handle := LoadIcon(0, IconID);
  868.       SetBounds(HorzMargin, VertMargin, 32, 32);
  869.     end;
  870.   FMsg := TLabel.Create(Self);
  871.   with FMsg do
  872.   begin
  873.     Name := 'Message';
  874.     Parent := Self;
  875.     WordWrap := True;
  876.     Caption := msg;
  877.     BoundsRect := TextRect;
  878.     SetBounds(
  879.       IconTextWidth - TextRect.Right + HorzMargin,
  880.       VertMargin,
  881.       TextRect.Right,
  882.       TextRect.Bottom);
  883.   end;
  884.   if mbOk in Buttons then
  885.     DefaultButton := mbOk
  886.   else if mbYes in Buttons then
  887.     DefaultButton := mbYes
  888.   else
  889.     DefaultButton := mbRetry;
  890.   if mbCancel in Buttons then
  891.     CancelButton := mbCancel
  892.   else if mbNo in Buttons then
  893.     CancelButton := mbNo
  894.   else
  895.     CancelButton := mbOk;
  896.   X := (ClientWidth - ButtonGroupWidth) div 2;
  897.   for B := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
  898.   begin
  899.     if B in Buttons then
  900.       with TButton.Create(Self) do
  901.       begin
  902.         Name := BUTTONNAMES_C[B];
  903.         Parent := Self;
  904.         Caption := BUTTONCAPTIONS_C[B];
  905.         ModalResult := MODALRESULTS_C[B];
  906.         if B = DefaultButton then
  907.           Default := True;
  908.         if B = CancelButton then
  909.           Cancel := True;
  910.         SetBounds(
  911.           X,
  912.           IconTextHeight + VertMargin + VertSpacing,
  913.           ButtonWidth,
  914.           ButtonHeight);
  915.         Inc(X, ButtonWidth + ButtonSpacing);
  916.         if B = mbHelp then
  917.           OnClick := HelpButtonClick;
  918.       end;
  919.   end;
  920.  
  921.   if not translateMsg then
  922.     FTranslator.OnRestrictProperty := Restrict;
  923. end;
  924.  
  925. procedure TIvMessageForm.Restrict(
  926.   translator: TIvTranslator;
  927.   obj: TObject;
  928.   const name: String;
  929.   var translate: Boolean);
  930. begin
  931.   if (obj = FMsg) and (CompareText(name, 'caption') = 0) then
  932.     translate := False;
  933. end;
  934.  
  935. procedure TIvMessageForm.HelpButtonClick(Sender: TObject);
  936. begin
  937.   Application.HelpContext(HelpContext);
  938. end;
  939.  
  940. function IvMessageBox(
  941.   const msg, captionMsg: String;
  942.   dlgType: TMsgDlgType;
  943.   buttons: TMsgDlgButtons;
  944.   helpContext: Longint;
  945.   dictionary: TIvDictionary): Integer;
  946. begin
  947.   Result := IvMessageBoxPos(
  948.     msg,
  949.     captionMsg,
  950.     dlgType,
  951.     buttons,
  952.     helpContext,
  953.     -1,
  954.     -1,
  955.     dictionary);
  956. end;
  957.  
  958. function IvMessageBoxPos(
  959.   const msg, captionMsg: String;
  960.   dlgType: TMsgDlgType;
  961.   buttons: TMsgDlgButtons;
  962.   helpContext: Longint;
  963.   x, y: Integer;
  964.   dictionary: TIvDictionary): Integer;
  965. var
  966.   box: TIvMessageForm;
  967. begin
  968.   box := TIvMessageForm.CreateML(Application, msg, captionMsg, dlgType, buttons, dictionary, True);
  969.  
  970.   try
  971.     box.HelpContext := helpContext;
  972.     if x >= 0 then
  973.       box.Left := x;
  974.     if y >= 0 then
  975.       box.Top := y;
  976.  
  977.     box.FTranslator.Translate;
  978.     Result := box.ShowModal;
  979.   finally
  980.     box.Free;
  981.   end;
  982. end;
  983.  
  984. procedure IvShowMessage(const msg: String; dictionary: TIvDictionary);
  985. begin
  986.   IvShowMessagePos(msg, -1, -1, dictionary);
  987. end;
  988.  
  989. procedure IvShowMessagePos(const msg: String; x, y: Integer; dictionary: TIvDictionary);
  990. begin
  991.   IvMessageBoxPos(msg, '',  mtCustom, [mbOK], 0, x, y, dictionary);
  992. end;
  993.  
  994. { Extended message functions }
  995.  
  996. function IvMessageBoxEx(
  997.   const msg, captionMsg: String;
  998.   dlgType: TMsgDlgType;
  999.   buttons: TMsgDlgButtons;
  1000.   helpContext: Longint;
  1001.   dictionary: TIvDictionary): Integer;
  1002. begin
  1003.   Result := IvMessageBoxPosEx(
  1004.     msg,
  1005.     captionMsg,
  1006.     dlgType,
  1007.     buttons,
  1008.     helpContext,
  1009.     -1,
  1010.     -1,
  1011.     dictionary);
  1012. end;
  1013.  
  1014. function IvMessageBoxPosEx(
  1015.   const msg, captionMsg: String;
  1016.   dlgType: TMsgDlgType;
  1017.   buttons: TMsgDlgButtons;
  1018.   helpContext: Longint;
  1019.   x, y: Integer;
  1020.   dictionary: TIvDictionary): Integer;
  1021. var
  1022.   box: TIvMessageForm;
  1023. begin
  1024.   box := TIvMessageForm.CreateML(Application, msg, captionMsg, dlgType, buttons, dictionary, False);
  1025.   try
  1026.     box.HelpContext := helpContext;
  1027.     if x >= 0 then
  1028.       box.Left := x;
  1029.     if y >= 0 then
  1030.       box.Top := y;
  1031.     box.FTranslator.Translate;
  1032.     Result := box.ShowModal;
  1033.   finally
  1034.     box.Free;
  1035.   end;
  1036. end;
  1037.  
  1038. { Input box }
  1039.  
  1040. type
  1041.   TIvInputForm = class(TIvMLForm)
  1042.   protected
  1043.     Edit: TEdit;
  1044.  
  1045.     constructor CreateML(
  1046.       owner: TComponent;
  1047.       const captionMsg, prompt: String;
  1048.       var value: String;
  1049.       dictionary: TIvDictionary);
  1050.   end;
  1051.  
  1052. constructor TIvInputForm.CreateML(
  1053.   owner: TComponent;
  1054.   const captionMsg, prompt: String;
  1055.   var value: String;
  1056.   dictionary: TIvDictionary);
  1057. var
  1058.   promptLabel: TLabel;
  1059.   dialogUnits: TPoint;
  1060.   buttonTop, buttonWidth, buttonHeight: Integer;
  1061. begin
  1062.   inherited CreateML(owner, dictionary);
  1063.  
  1064.   Canvas.Font := Font;
  1065.   Caption := captionMsg;
  1066.   DialogUnits := GetAveCharSize(Canvas);
  1067.   BorderStyle := bsDialog;
  1068.   ClientWidth := MulDiv(180, DialogUnits.X, 4);
  1069.   ClientHeight := MulDiv(63, DialogUnits.Y, 8);
  1070.   Position := poScreenCenter;
  1071.  
  1072.   promptLabel := TLabel.Create(Self);
  1073.   with promptLabel do
  1074.   begin
  1075.     Parent := Self;
  1076.     AutoSize := True;
  1077.     Left := MulDiv(8, DialogUnits.X, 4);
  1078.     Top := MulDiv(8, DialogUnits.Y, 8);
  1079.     Caption := dictionary.Translate(prompt);
  1080.   end;
  1081.  
  1082.   Edit := TEdit.Create(Self);
  1083.   with Edit do
  1084.   begin
  1085.     Parent := Self;
  1086.     Left := PromptLabel.Left;
  1087.     Top := MulDiv(19, DialogUnits.Y, 8);
  1088.     Width := MulDiv(164, DialogUnits.X, 4);
  1089.     MaxLength := 255;
  1090.     Text := Value;
  1091.     SelectAll;
  1092.   end;
  1093.  
  1094.   buttonTop := MulDiv(41, DialogUnits.Y, 8);
  1095.   buttonWidth := MulDiv(50, DialogUnits.X, 4);
  1096.   buttonHeight := MulDiv(14, DialogUnits.Y, 8);
  1097.   with TButton.Create(Self) do
  1098.   begin
  1099.     Parent := Self;
  1100.     Caption := 'OK';
  1101.     ModalResult := mrOk;
  1102.     Default := True;
  1103.     SetBounds(
  1104.       MulDiv(38, DialogUnits.X, 4),
  1105.       buttonTop,
  1106.       buttonWidth,
  1107.       buttonHeight);
  1108.   end;
  1109.  
  1110.   with TButton.Create(Self) do
  1111.   begin
  1112.     Parent := Self;
  1113.     Caption := 'Cancel';
  1114.     ModalResult := mrCancel;
  1115.     Cancel := True;
  1116.     SetBounds(
  1117.       MulDiv(92, DialogUnits.X, 4),
  1118.       ButtonTop,
  1119.       ButtonWidth,
  1120.       ButtonHeight);
  1121.   end;
  1122.  
  1123.   FTranslator.Translate;
  1124. end;
  1125.  
  1126. function IvInputQuery(
  1127.   const captionMsg, prompt: String;
  1128.   var value: String;
  1129.   dictionary: TIvDictionary): Boolean;
  1130. var
  1131.   form: TIvInputForm;
  1132. begin
  1133.   Result := False;
  1134.   form := nil;
  1135.  
  1136.   try
  1137.     form := TIvInputForm.CreateML(Application, captionMsg, prompt, value, dictionary);
  1138.     if form.ShowModal = mrOk then
  1139.     begin
  1140.       value := form.Edit.Text;
  1141.       Result := True;
  1142.     end;
  1143.   finally
  1144.     form.Free;
  1145.   end;
  1146. end;
  1147.  
  1148. function IvInputBox(
  1149.   const captionMsg, prompt, def: String;
  1150.   dictionary: TIvDictionary): String;
  1151. begin
  1152.   Result := def;
  1153.   IvInputQuery(captionMsg, prompt, Result, dictionary);
  1154. end;
  1155.  
  1156. { TIvSelectDirDlg }
  1157.  
  1158. type
  1159.   TIvPathLabel = class(TCustomLabel)
  1160.   protected
  1161.     procedure Paint; override;
  1162.  
  1163.   public
  1164.     constructor Create(owner: TComponent); override;
  1165.  
  1166.   published
  1167.     property Alignment;
  1168.     property Transparent;
  1169.   end;
  1170.  
  1171.   EInvalidDrive = class(Exception);
  1172.  
  1173.   TIvSelectDirDlg = class(TIvMLForm)
  1174.     DirList: TDirectoryListBox;
  1175.     DirEdit: TEdit;
  1176.     DriveList: TDriveComboBox;
  1177.     DirLabel: TIvPathLabel;
  1178.     OKButton: TButton;
  1179.     CancelButton: TButton;
  1180.     HelpButton: TButton;
  1181.     NetButton: TButton;
  1182.     FileList: TFileListBox;
  1183.  
  1184.     procedure DirListChange(Sender: TObject);
  1185. {$IFDEF DIR_CHECK}
  1186.     procedure DriveListClick(Sender: TObject);
  1187. {$ENDIF}
  1188.     procedure FormCreate(Sender: TObject);
  1189.     procedure DriveListChange(Sender: TObject);
  1190.     procedure NetClick(Sender: TObject);
  1191.     procedure OKClick(Sender: TObject);
  1192.     procedure HelpButtonClick(Sender: TObject);
  1193.  
  1194.   private
  1195.     FAllowCreate: Boolean;
  1196.     FPrompt: Boolean;
  1197. {$IFDEF DIR_CHECK}
  1198.     FOldDrive: Char;
  1199. {$ENDIF}
  1200.     WNetConnectDialog: function (WndParent: HWND; IType: Longint): Longint;
  1201.  
  1202.     procedure SetAllowCreate(value: Boolean);
  1203.     procedure SetDirectory(const value: String);
  1204.     function GetDirectory: String;
  1205.  
  1206.   public
  1207.     constructor CreateML(owner: TComponent; dictionary: TIvDictionary);
  1208.  
  1209.     property Directory: String read GetDirectory write SetDirectory;
  1210.     property AllowCreate: Boolean read FAllowCreate write SetAllowCreate default False;
  1211.     property Prompt: Boolean read FPrompt write FPrompt default False;
  1212.   end;
  1213.  
  1214. {$IFNDEF IVWIDE}
  1215. const
  1216.   Slashes: array [False..True] of PChar = ('','\');
  1217. {$ENDIF}
  1218.  
  1219. function SlashSep(const Path, S: String): String;
  1220. begin
  1221. {$IFDEF IVWIDE}
  1222.   if AnsiLastChar(Path)^ <> '\' then
  1223.     Result := Path + '\' + S
  1224.   else
  1225.     Result := Path + S;
  1226. {$ELSE}
  1227.   Result := Format('%s%s%s',[Path, Slashes[Path[Length(Path)] <> '\'], S]);
  1228. {$ENDIF}
  1229. end;
  1230.  
  1231. { TIvPathLabel }
  1232.  
  1233. constructor TIvPathLabel.Create(owner: TComponent);
  1234. begin
  1235.   inherited Create(owner);
  1236.   WordWrap := False;
  1237.   AutoSize := False;
  1238.   ShowAccelChar := False;
  1239. end;
  1240.  
  1241. procedure TIvPathLabel.Paint;
  1242. const
  1243.   Alignments: array[TAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);
  1244. var
  1245.   Rect: TRect;
  1246.   Temp: String;
  1247. {$IFNDEF WIN32}
  1248.   buffer: array[0..255] of Char;
  1249. {$ENDIF}
  1250. begin
  1251.   with Canvas do
  1252.   begin
  1253.     Rect := ClientRect;
  1254.     if not Transparent then
  1255.     begin
  1256.       Brush.Color := Self.Color;
  1257.       Brush.Style := bsSolid;
  1258.       FillRect(Rect);
  1259.     end;
  1260.     Brush.Style := bsClear;
  1261.     Temp := MinimizeName(Caption, Canvas, Rect.Right - Rect.Left);
  1262.     DrawText(
  1263.       Canvas.Handle,
  1264. {$IFDEF WIN32}PChar({$ELSE}StrPCopy(buffer,{$ENDIF}
  1265.       Temp),
  1266.       Length(Temp),
  1267.       Rect,
  1268.       DT_NOPREFIX or Alignments[Alignment]);
  1269.   end;
  1270. end;
  1271.  
  1272.  
  1273. { TIvSelectDirDlg }
  1274.  
  1275. {$IFDEF POIS}
  1276. function DiskInDrive(Drive: Char): Boolean;
  1277. var
  1278.   ErrorMode: word;
  1279. begin
  1280.   // Make it upper case
  1281.  
  1282.   Drive := UpCase(Drive);
  1283.  
  1284.   // Make sure it's a letter
  1285.  
  1286.   if not (Drive in ['A'..'Z']) then
  1287.     raise Exception.Create(Format('%s is not a valid driveletter', [Drive]));
  1288.  
  1289.   // Turn off critical errors
  1290.  
  1291.   ErrorMode := SetErrorMode(SEM_FailCriticalErrors);
  1292.   try
  1293.     // drive 1 = a, 2 = b, 3 = c, etc.
  1294.  
  1295.     if DiskSize(Ord(Drive) - $40) = -1 then
  1296.       Result := False
  1297.     else
  1298.       Result := True;
  1299.   finally
  1300.     // Restore old error mode
  1301.  
  1302.     SetErrorMode(ErrorMode);
  1303.   end;
  1304. end;
  1305.  
  1306. procedure ProcessPath(
  1307.   const EditText: String;
  1308.   var Drive: Char;
  1309.   var DirPart: String;
  1310.   var FilePart: String);
  1311. var
  1312.   SaveDir: string;
  1313.   Root: string;
  1314. begin
  1315.   GetDir(0, SaveDir);
  1316.   Drive := SaveDir[1];
  1317.   DirPart := EditText;
  1318.   if (DirPart[1] = '[') and (AnsiLastChar(DirPart)^ = ']') then
  1319.     DirPart := Copy(DirPart, 2, Length(DirPart) - 2)
  1320.   else
  1321.   begin
  1322.     Root := ExtractFileDrive(DirPart);
  1323.     if Length(Root) = 0 then
  1324.       Root := ExtractFileDrive(SaveDir)
  1325.     else
  1326.       Delete(DirPart, 1, Length(Root));
  1327.     if (Length(Root) >= 2) and (Root[2] = ':') then
  1328.       Drive := Root[1]
  1329.     else
  1330.       Drive := #0;
  1331.   end;
  1332.  
  1333.   if (not DiskInDrive(Drive)) then
  1334.     raise EInvalidDrive.CreateFmt('No disk in drive %s', [UpCase(Drive)]);
  1335.  
  1336.   try
  1337.     if DirectoryExists(Root) then
  1338.       ChDir(Root);
  1339.     FilePart := ExtractFileName (DirPart);
  1340.     if Length(DirPart) = (Length(FilePart) + 1) then
  1341.       DirPart := '\'
  1342.     else if Length(DirPart) > Length(FilePart) then
  1343.       SetLength(DirPart, Length(DirPart) - Length(FilePart) - 1)
  1344.     else
  1345.     begin
  1346.       GetDir(0, DirPart);
  1347.       Delete(DirPart, 1, Length(ExtractFileDrive(DirPart)));
  1348.       if Length(DirPart) = 0 then
  1349.         DirPart := '\';
  1350.     end;
  1351.     if Length(DirPart) > 0 then
  1352.       ChDir (DirPart);  {first go to our new directory}
  1353.     if (Length(FilePart) > 0) and not
  1354.        (((Pos('*', FilePart) > 0) or (Pos('?', FilePart) > 0)) or
  1355.        FileExists(FilePart)) then
  1356.     begin
  1357.       ChDir(FilePart);
  1358.       if Length(DirPart) = 1 then
  1359.         DirPart := '\' + FilePart
  1360.       else
  1361.         DirPart := DirPart + '\' + FilePart;
  1362.       FilePart := '';
  1363.     end;
  1364.     if Drive = #0 then
  1365.       DirPart := Root + DirPart;
  1366.   finally
  1367.     if DirectoryExists(SaveDir) then
  1368.       ChDir(SaveDir);  { restore original directory }
  1369.   end;
  1370. end;
  1371. {$ENDIF}
  1372.  
  1373. constructor TIvSelectDirDlg.CreateML(owner: TComponent; dictionary: TIvDictionary);
  1374. begin
  1375.   inherited CreateML(owner, dictionary);
  1376.   Caption := 'Select Directory'; {ivde}
  1377.   BorderStyle := bsDialog;
  1378.   ClientWidth := 424;
  1379.   ClientHeight := 255;
  1380.   Position := poScreenCenter;
  1381.  
  1382.   DirEdit := TEdit.Create(Self);
  1383.   with DirEdit do
  1384.   begin
  1385.     Parent := Self;
  1386.     SetBounds(8, 24, 313, 20);
  1387.     Visible := False;
  1388.     TabOrder := 0;
  1389.   end;
  1390.  
  1391.   with TLabel.Create(Self) do
  1392.   begin
  1393.     Parent := Self;
  1394.     SetBounds(8, 8, 92, 13);
  1395.     FocusControl := DirEdit;
  1396.     Caption := 'Directory &Name:'; {ivde}
  1397.   end;
  1398.  
  1399.   DriveList := TDriveComboBox.Create(Self);
  1400.   with DriveList do
  1401.   begin
  1402.     Parent := Self;
  1403.     SetBounds(232, 192, 185, 19);
  1404.     TabOrder := 4;
  1405.     OnChange := DriveListChange;
  1406. {$IFDEF DIR_CHECK}
  1407.     OnClick  := DriveListClick;
  1408. {$ENDIF}
  1409.   end;
  1410.  
  1411.   with TLabel.Create(Self) do
  1412.   begin
  1413.     Parent := Self;
  1414.     SetBounds(232, 176, 41, 13);
  1415.     Caption := 'D&rives:'; {ivde}
  1416.     FocusControl := DriveList;
  1417.   end;
  1418.  
  1419.   DirLabel := TIvPathLabel.Create(Self);
  1420.   with DirLabel do
  1421.   begin
  1422.     Parent := Self;
  1423.     SetBounds(120, 8, 213, 13);
  1424.   end;
  1425.  
  1426.   DirList := TDirectoryListBox.Create(Self);
  1427.   with DirList do
  1428.   begin
  1429.     Parent := Self;
  1430.     SetBounds(8, 72, 213, 138);
  1431.     TabOrder := 1;
  1432.     TabStop := True;
  1433.     ItemHeight := 17;
  1434.     IntegralHeight := True;
  1435.     OnChange := DirListChange;
  1436.   end;
  1437.  
  1438.   with TLabel.Create(Self) do
  1439.   begin
  1440.     Parent := Self;
  1441.     SetBounds(8, 56, 66, 13);
  1442.     Caption := '&Directories:'; {ivde}
  1443.     FocusControl := DirList;
  1444.   end;
  1445.  
  1446.   FileList := TFileListBox.Create(Self);
  1447.   with FileList do
  1448.   begin
  1449.     Parent := Self;
  1450.     SetBounds(232, 72, 185, 93);
  1451.     TabOrder := 2;
  1452.     TabStop := True;
  1453.     FileType := [ftNormal];
  1454.     Mask := '*.*';
  1455.     Font.Color := clGrayText;
  1456.     ItemHeight := 13;
  1457.   end;
  1458.  
  1459.   with TLabel.Create(Self) do
  1460.   begin
  1461.     Parent := Self;
  1462.     SetBounds(232, 56, 57, 13);
  1463.     Caption := '&Files: (*.*)'; {ivde}
  1464.     FocusControl := FileList;
  1465.   end;
  1466.  
  1467.   NetButton := TButton.Create(Self);
  1468.   with NetButton do
  1469.   begin
  1470.     Parent := Self;
  1471.     SetBounds(8, 224, 75, 25);
  1472.     Visible := False;
  1473.     TabOrder := 6;
  1474.     Caption := 'Ne&twork...'; {ivde}
  1475.     OnClick := NetClick;
  1476.   end;
  1477.  
  1478.   OKButton := TButton.Create(Self);
  1479.   with OKButton do
  1480.   begin
  1481.     Parent := Self;
  1482.     SetBounds(172, 224, 75, 25);
  1483.     TabOrder := 4;
  1484.     OnClick := OKClick;
  1485.     Caption := 'OK'; {ivde}
  1486.     ModalResult := 1;
  1487.     Default := True;
  1488.   end;
  1489.  
  1490.   CancelButton := TButton.Create(Self);
  1491.   with CancelButton do
  1492.   begin
  1493.     Parent := Self;
  1494.     SetBounds(256, 224, 75, 25);
  1495.     TabOrder := 5;
  1496.     Cancel := True;
  1497.     Caption := 'Cancel'; {ivde}
  1498.     ModalResult := 2;
  1499.   end;
  1500.  
  1501.   HelpButton := TButton.Create(Self);
  1502.   with HelpButton do
  1503.   begin
  1504.     Parent := Self;
  1505.     SetBounds(340, 224, 77, 27);
  1506.     TabOrder := 7;
  1507.     Caption := '&Help'; {ivde}
  1508.     OnClick := HelpButtonClick;
  1509.   end;
  1510.  
  1511.   FormCreate(Self);
  1512.   FTranslator.Translate;
  1513. end;
  1514.  
  1515. procedure TIvSelectDirDlg.HelpButtonClick(Sender: TObject);
  1516. begin
  1517.   Application.HelpContext(HelpContext);
  1518. end;
  1519.  
  1520. procedure TIvSelectDirDlg.DirListChange(Sender: TObject);
  1521. begin
  1522.   DirLabel.Caption := DirList.Directory;
  1523.   FileList.Directory := DirList.Directory;
  1524.   DirEdit.Text := DirLabel.Caption;
  1525.   DirEdit.SelectAll;
  1526. end;
  1527.  
  1528. {$IFDEF DIR_CHECK}
  1529. procedure TIvSelectDirDlg.DriveListClick(Sender: TObject);
  1530. begin
  1531.   FOldDrive := DriveList.Drive;
  1532. end;
  1533. {$ENDIF}
  1534.  
  1535. procedure TIvSelectDirDlg.DriveListChange(Sender: TObject);
  1536. begin
  1537.   try
  1538.     DirList.Drive := DriveList.Drive;
  1539.   except
  1540. {$IFDEF DIR_CHECK}
  1541.     DriveList.Drive := FOldDrive;
  1542. {$ENDIF}
  1543.     raise;
  1544.   end;
  1545. end;
  1546.  
  1547. procedure TIvSelectDirDlg.FormCreate(Sender: TObject);
  1548. var
  1549.   UserHandle: THandle;
  1550.   NetDriver: THandle;
  1551.   WNetGetCaps: function (Flags: Word): Word;
  1552. begin
  1553.   { is network access enabled? }
  1554. {$IFDEF WIN32}
  1555.   UserHandle := GetModuleHandle(User32);
  1556. {$ELSE}
  1557.   UserHandle := GetModuleHandle('USER');
  1558. {$ENDIF}
  1559.   @WNetGetCaps := GetProcAddress(UserHandle, 'WNETGETCAPS');
  1560.   if @WNetGetCaps <> nil then
  1561.   begin
  1562.     NetDriver := WNetGetCaps(Word(-1));
  1563.     if NetDriver <> 0 then
  1564.     begin
  1565.       @WNetConnectDialog := GetProcAddress(NetDriver, 'WNETCONNECTDIALOG');
  1566.       NetButton.Visible := @WNetConnectDialog <> nil;
  1567.     end;
  1568.   end;
  1569.  
  1570.   FAllowCreate := False;
  1571.   DirLabel.BoundsRect := DirEdit.BoundsRect;
  1572.   DirListChange(Self);
  1573. end;
  1574.  
  1575. procedure TIvSelectDirDlg.SetAllowCreate(Value: Boolean);
  1576. begin
  1577.   if Value <> FAllowCreate then
  1578.   begin
  1579.     FAllowCreate := Value;
  1580.     DirLabel.Visible := not FAllowCreate;
  1581.     DirEdit.Visible := FAllowCreate;
  1582.   end;
  1583. end;
  1584.  
  1585. procedure TIvSelectDirDlg.SetDirectory(const Value: string);
  1586. var
  1587.   Temp: string;
  1588. begin
  1589.   if Value <> '' then
  1590.   begin
  1591.     Temp := ExpandFileName(SlashSep(Value, '*.*'));
  1592.     if (Length(Temp) >= 3) and (Temp[2] = ':') then
  1593.     begin
  1594.       DriveList.Drive := Temp[1];
  1595.       Temp := ExtractFilePath(Temp);
  1596.       try
  1597.         DirList.Directory := Copy(Temp, 1, Length(Temp) - 1);
  1598.       except
  1599.         on EInOutError do
  1600.         begin
  1601.           GetDir(0, Temp);
  1602.           DriveList.Drive := Temp[1];
  1603.           DirList.Directory := Temp;
  1604.         end;
  1605.       end;
  1606.     end;
  1607.   end;
  1608. end;
  1609.  
  1610. function TIvSelectDirDlg.GetDirectory: string;
  1611. begin
  1612.   if FAllowCreate then
  1613.     Result := DirEdit.Text
  1614.   else
  1615.     Result := DirLabel.Caption;
  1616. end;
  1617.  
  1618. procedure TIvSelectDirDlg.NetClick(Sender: TObject);
  1619. begin
  1620.   if Assigned(WNetConnectDialog) then
  1621.     WNetConnectDialog(Handle, WNTYPE_DRIVE);
  1622. end;
  1623.  
  1624. procedure TIvSelectDirDlg.OKClick(Sender: TObject);
  1625. begin
  1626.   if AllowCreate and Prompt and (not DirectoryExists(Directory)) and
  1627.     (IvMessageBox(
  1628.       'The specified directory does not exist. Create it?', {ivde}
  1629.       '',
  1630.       mtConfirmation,
  1631.       [mbYes, mbNo],
  1632.       0,
  1633.       FTranslator.Dictionary) <> mrYes) then
  1634.     ModalResult := 0;
  1635. end;
  1636.  
  1637. function IvSelectDirectory(
  1638.   var directory: String;
  1639.   options: TSelectDirOpts;
  1640.   helpContext: Longint;
  1641.   dictionary: TIvDictionary): Boolean;
  1642. var
  1643.   dialog: TIvSelectDirDlg;
  1644. begin
  1645.   dialog := TIvSelectDirDlg.CreateML(Application, dictionary);
  1646.   try
  1647.     dialog.Directory := Directory;
  1648.     dialog.AllowCreate := sdAllowCreate in Options;
  1649.     dialog.Prompt := sdPrompt in Options;
  1650.  
  1651.     { scale to screen res }
  1652.     
  1653.     if Screen.PixelsPerInch <> 96 then
  1654.     begin
  1655.       dialog.ScaleBy(Screen.PixelsPerInch, 96);
  1656.       dialog.FileList.ParentFont := True;
  1657.       dialog.Left := (Screen.Width div 2) - (dialog.Width div 2);
  1658.       dialog.Top := (Screen.Height div 2) - (dialog.Height div 2);
  1659.       dialog.FileList.Font.Color := clGrayText;
  1660.     end;
  1661.  
  1662.     if helpContext = 0 then
  1663.     begin
  1664.       dialog.HelpButton.Visible := False;
  1665.       dialog.OKButton.Left := dialog.CancelButton.Left;
  1666.       dialog.CancelButton.Left := dialog.HelpButton.Left;
  1667.     end
  1668.     else
  1669.       dialog.HelpContext := helpContext;
  1670.  
  1671.     Result := dialog.ShowModal = mrOK;
  1672.     if Result then
  1673.     begin
  1674.       Directory := dialog.Directory;
  1675.       if sdPerformCreate in Options then
  1676.         ForceDirectories(Directory);
  1677.     end;
  1678.   finally
  1679.     dialog.Free;
  1680.   end;
  1681. end;
  1682.  
  1683. end.
  1684.